﻿using System;

namespace Argos.Scheduling
{
	/// <summary>
	/// Represents a schedule that defines occurrences with not regularity.
	/// </summary>
	[Serializable]
	public sealed class CustomSchedule : Schedule
	{

		#region public override void AddDateTime(DateTime start, TimeSpan duration)

		/// <summary>
		/// Adds the given date, time and duration as an occurrence to the schedule.
		/// </summary>
		/// <param name="dt">The date and time for the start of the occurrence.</param>
		/// <param name="duration">The duration for the occurrence.</param>
		public override void AddDateTime(DateTime start, TimeSpan duration)
		{
			this.Entries.Add(new Entry(start, duration));
		}

		#endregion

		#region public void AddOccurrence(Occurrence occurrence)

		/// <summary>
		/// Adds a new occurrence to the schedule.
		/// </summary>
		/// <param name="occurrence">The occurrence to add.</param>
		public void AddOccurrence(Occurrence occurrence)
		{
			this.Entries.Add(new Entry(occurrence));
		}

		#endregion



		/// <summary>
		/// Represents an entry in a custom schedule.
		/// </summary>
		[Serializable]
		public sealed class Entry : ScheduleEntry
		{

			#region #ctor: public Entry(DateTime start)

			/// <summary>
			/// Creates a new instance of the class.
			/// </summary>
			/// <param name="start">The starting date and time of the entry.</param>
			public Entry(DateTime start) : this(start, TimeSpan.Zero) { }

			#endregion

			#region #ctor: public Entry(DateTime start, TimeSpan duration)

			/// <summary>
			/// Creates a new instance of the class.
			/// </summary>
			/// <param name="start">The starting date and time of the entry.</param>
			/// <param name="duration">The duration for the entry.</param>
			public Entry(DateTime start, TimeSpan duration)
			{
				this.Start = start;
				this.Duration = duration;
			}

			#endregion

			#region #ctor: public Entry(Occurrence occurrence)

			/// <summary>
			/// Creates a new instance of the class.
			/// </summary>
			/// <param name="occurrence">The occurrence to create the entry from.</param>
			public Entry(Occurrence occurrence) : this(occurrence.Start, occurrence.Duration) { }

			#endregion



			#region public TimeSpan Duration { get; private set; }

			/// <summary>
			/// Returns the duration of the entry.
			/// </summary>
			public TimeSpan Duration { get; private set; }

			#endregion

			#region public DateTime Start { get; private set; }

			/// <summary>
			/// Returns the start date and time of the entry.
			/// </summary>
			public DateTime Start { get; private set; }

			#endregion



			public override Occurrence GetNextOccurrence(DateTime after)
			{
				if (this.Start > after)
				{
					return new Occurrence(this.Start, this.Duration);
				}
				return null;
			}

			public override Occurrence GetPreviousOccurrence(DateTime before)
			{
				if (this.Start < before)
				{
					return new Occurrence(this.Start, this.Duration);
				}
				return null;
			}

			#region public override string ToString()

			/// <summary>
			/// Returns the string representation of the entry.
			/// </summary>
			public override string ToString()
			{
				if (this.Duration > TimeSpan.Zero)
				{
					return string.Format("{0} to {1}", this.Start, this.Start.Add(this.Duration));
				}
				return this.Start.ToString();
			}

			#endregion

		}

	}
}
